inspector: life-cycle fixes
authorMatthias Clasen <mclasen@redhat.com>
Fri, 26 Sep 2014 03:05:15 +0000 (23:05 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Fri, 26 Sep 2014 03:05:15 +0000 (23:05 -0400)
When closing the inspector before the main window, we must take
care to sever all signal connections and weak refs, otherwise
things will go bad when the window is closed later.

gtk/inspector/classes-list.c
gtk/inspector/css-editor.c
gtk/inspector/prop-list.c
gtk/inspector/widget-tree.c

index 2d21265aaea0d1b68f99c56b0ab8adf3b03708ed..1fc313082cb0441a92fd25ca087dffae41e308ac 100644 (file)
@@ -225,20 +225,23 @@ gtk_inspector_classes_list_init (GtkInspectorClassesList *cl)
   gtk_widget_init_template (GTK_WIDGET (cl));
 }
 
-static void remove_dead_object (gpointer data, GObject *dead_object);
+static void gtk_inspector_classes_list_remove_dead_object (gpointer data, GObject *dead_object);
 
 static void
 cleanup_context (GtkInspectorClassesList *cl)
 {
   if (cl->priv->context)
-    g_object_weak_unref (G_OBJECT (cl->priv->context), remove_dead_object, cl);
+    {
+      g_object_weak_unref (G_OBJECT (cl->priv->context),gtk_inspector_classes_list_remove_dead_object, cl);
+      cl->priv->context = NULL;
+    }
 
-  gtk_list_store_clear (cl->priv->model);
-  cl->priv->context = NULL;
+  if (cl->priv->model)
+    gtk_list_store_clear (cl->priv->model);
 }
 
 static void
-remove_dead_object (gpointer data, GObject *dead_object)
+gtk_inspector_classes_list_remove_dead_object (gpointer data, GObject *dead_object)
 {
   GtkInspectorClassesList *cl = data;
 
@@ -267,7 +270,7 @@ gtk_inspector_classes_list_set_object (GtkInspectorClassesList *cl,
 
   cl->priv->context = gtk_widget_get_style_context (GTK_WIDGET (object));
 
-  g_object_weak_ref (G_OBJECT (cl->priv->context), remove_dead_object, cl);
+  g_object_weak_ref (G_OBJECT (cl->priv->context), gtk_inspector_classes_list_remove_dead_object, cl);
 
   hash_context = get_hash_context (cl);
   if (hash_context)
@@ -290,10 +293,23 @@ gtk_inspector_classes_list_set_object (GtkInspectorClassesList *cl,
     read_classes_from_style_context (cl);
 }
 
+static void
+gtk_inspector_classes_list_finalize (GObject *object)
+{
+  GtkInspectorClassesList *cl = GTK_INSPECTOR_CLASSES_LIST (object);
+
+  cleanup_context (cl);
+  
+  G_OBJECT_CLASS (gtk_inspector_classes_list_parent_class)->finalize (object);
+}
+
 static void
 gtk_inspector_classes_list_class_init (GtkInspectorClassesListClass *klass)
 {
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gtk_inspector_classes_list_finalize;
 
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/inspector/classes-list.ui");
   gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, model);
index d8f518192036bc8df041e6d40f0596ec70b8b495..7bfaa26686de7ea8986629640616ed61fbfecba2 100644 (file)
@@ -67,6 +67,9 @@ struct _GtkInspectorCssEditorPrivate
   guint timeout;
 };
 
+static void gtk_inspector_css_editor_remove_dead_object (gpointer  data,
+                                                         GObject  *dead_object);
+
 G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorCssEditor, gtk_inspector_css_editor, GTK_TYPE_BOX)
 
 static void
@@ -333,6 +336,30 @@ create_provider (GtkInspectorCssEditor *ce)
                     G_CALLBACK (show_parsing_error), ce);
 }
 
+static void
+destroy_provider (GtkInspectorCssEditor *ce)
+{
+  if (ce->priv->global)
+    {
+      gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (),
+                                                    GTK_STYLE_PROVIDER (ce->priv->provider));
+      g_object_unref (ce->priv->provider);
+      ce->priv->provider = NULL;
+    }
+  else if (ce->priv->context)
+    {
+      GtkStyleProvider *provider;
+
+      provider = g_object_get_data (G_OBJECT (ce->priv->context),
+                                    GTK_INSPECTOR_CSS_EDITOR_PROVIDER);
+      gtk_style_context_remove_provider (ce->priv->context, provider);
+      g_object_set_data (G_OBJECT (ce->priv->context),
+                         GTK_INSPECTOR_CSS_EDITOR_PROVIDER,
+                         NULL);
+    }
+}
+  
+
 static void
 gtk_inspector_css_editor_init (GtkInspectorCssEditor *ce)
 {
@@ -398,6 +425,16 @@ finalize (GObject *object)
   if (ce->priv->timeout != 0)
     g_source_remove (ce->priv->timeout);
 
+  destroy_provider (ce);
+  if (ce->priv->context)
+    {
+      g_object_weak_unref (G_OBJECT (ce->priv->context), gtk_inspector_css_editor_remove_dead_object, ce);
+      g_object_set_data (G_OBJECT (ce->priv->context),
+                         GTK_INSPECTOR_CSS_EDITOR_TEXT,
+                         NULL);
+      ce->priv->context = NULL;
+    }
+
   G_OBJECT_CLASS (gtk_inspector_css_editor_parent_class)->finalize (object);
 }
 
@@ -427,7 +464,7 @@ gtk_inspector_css_editor_class_init (GtkInspectorCssEditorClass *klass)
 }
 
 static void
-remove_dead_object (gpointer data, GObject *dead_object)
+gtk_inspector_css_editor_remove_dead_object (gpointer data, GObject *dead_object)
 {
   GtkInspectorCssEditor *ce = data;
 
@@ -447,7 +484,7 @@ gtk_inspector_css_editor_set_object (GtkInspectorCssEditor *ce,
 
   if (ce->priv->context)
     {
-      g_object_weak_unref (G_OBJECT (ce->priv->context), remove_dead_object, ce);
+      g_object_weak_unref (G_OBJECT (ce->priv->context), gtk_inspector_css_editor_remove_dead_object, ce);
       text = get_current_text (GTK_TEXT_BUFFER (ce->priv->text));
       g_object_set_data_full (G_OBJECT (ce->priv->context),
                               GTK_INSPECTOR_CSS_EDITOR_TEXT,
@@ -472,7 +509,7 @@ gtk_inspector_css_editor_set_object (GtkInspectorCssEditor *ce,
   set_initial_text (ce);
   disable_toggled (ce->priv->disable_button, ce);
 
-  g_object_weak_ref (G_OBJECT (ce->priv->context), remove_dead_object, ce);
+  g_object_weak_ref (G_OBJECT (ce->priv->context), gtk_inspector_css_editor_remove_dead_object, ce);
 }
 
 // vim: set et sw=2 ts=2:
index 707e4a234c710f1ac5eabb3277c5d509587a8502..139977748edef21231aca7eb91c01aef4547efc0 100644 (file)
@@ -391,14 +391,14 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl,
   g_free (props);
 
   if (GTK_IS_WIDGET (object))
-    g_signal_connect_swapped (object, "destroy", G_CALLBACK (cleanup_object), pl);
+    g_signal_connect_object (object, "destroy", G_CALLBACK (cleanup_object), pl, G_CONNECT_SWAPPED);
 
   /* Listen for updates */
   pl->priv->notify_handler_id =
-      g_signal_connect (object,
-                        pl->priv->child_properties ? "child-notify" : "notify",
-                        G_CALLBACK (gtk_inspector_prop_list_prop_changed_cb),
-                        pl);
+      g_signal_connect_object (object,
+                               pl->priv->child_properties ? "child-notify" : "notify",
+                               G_CALLBACK (gtk_inspector_prop_list_prop_changed_cb),
+                               pl, 0);
 
   gtk_widget_show (GTK_WIDGET (pl));
 
index 6f3ec6ac64fd12edd399e44b9f86789fc8cb783c..8fd61308661fd89898c90f58b2dcb7ac354ec17b 100644 (file)
@@ -88,7 +88,7 @@ typedef struct
 } ObjectData;
 
 static void
-remove_dead_object (gpointer data, GObject *dead_object)
+gtk_widget_tree_remove_dead_object (gpointer data, GObject *dead_object)
 {
   ObjectData *od = data;
 
@@ -113,7 +113,7 @@ object_data_free (gpointer data)
   gtk_tree_row_reference_free (od->row);
 
   if (od->object)
-    g_object_weak_unref (od->object, remove_dead_object, od);
+    g_object_weak_unref (od->object, gtk_widget_tree_remove_dead_object, od);
 
   g_free (od);
 }
@@ -333,7 +333,7 @@ gtk_inspector_widget_tree_append_object (GtkInspectorWidgetTree *wt,
   gtk_tree_path_free (path);
 
   g_hash_table_insert (wt->priv->iters, object, od);
-  g_object_weak_ref (object, remove_dead_object, od);
+  g_object_weak_ref (object, gtk_widget_tree_remove_dead_object, od);
 
   g_free (address);